﻿/// <reference path="_namespace.js" />
/// <reference path="../../collections/ArrayList.js" />
/// <reference path="IGameComponent.js" />
/// <reference path="IUpdateable.js" />
/// <reference path="IDrawable.js" />

/*****************************************************************************
Ajaxna library class definition. Inheriting from ajax.BaseObject.
Author: krobinson 10/14/2008 5:20:15 PM.
Class:  ajax.xna.framework.GameComponentCollection
*****************************************************************************/

$addNamespace("ajax.xna.framework");
$imports("ajax.xna.framework.IGameComponent");
$imports("ajax.xna.framework.IUpdateable");
$imports("ajax.xna.framework.IDrawable");
//-----------------------------------------------------------------------------

ajax.xna.framework.GameComponentCollection = function(doc)
{///<field name="updateableComponents" type="Array">Maintains the list of IUpdateable game components, sorted in updateOrder.</field>
 ///<field name="drawableComponents" type="Array">Maintains the list of IDrawable game components, sorted in drawOrder.</field>
    ajax.xna.framework.GameComponentCollection.superConstructor.apply(this, arguments);  
    this.updateableComponents = new Array();
    this.drawableComponents   = new Array();

    // Create delegates...
    this._updateableUpdateOrderChangedDelegate = Function.createBinding(this, this._updateableUpdateOrderChanged);
    this._drawableDrawOrderChangedDelegate = Function.createBinding(this, this._drawableDrawOrderChanged);
}
$extend("ajax.xna.framework.GameComponentCollection", "ajax.collections.ArrayList");
if ($getDesignMode())
    ajax.xna.framework.GameComponentCollection.prototype = ajax.collections.ArrayList.prototype;
//-----------------------------------------------------------------------------
// internal arrays...
ajax.xna.framework.GameComponentCollection.prototype.updateableComponents = Array.prototype;
ajax.xna.framework.GameComponentCollection.prototype.drawableComponents = Array.prototype;
//-----------------------------------------------------------------------------

ajax.xna.framework.GameComponentCollection.prototype._onComponentAdded = function(item)
{
    // Add handlers and to internal lists.
    item = ajax.xna.framework.IGameComponent.cast(item);
    if (ajax.lang.implementsInterface(Object.getConstructorName(item), ajax.xna.framework.IUpdateable.getFunctionName()))
    {
        item = ajax.xna.framework.IUpdateable.cast(item);
        var index = this.updateableComponents.indexOf(item);
        if (index < 0)
        {           
            index = 0;
            while (index < this.updateableComponents.length && this.updateableComponents[index].get_updateOrder() >= item.get_updateOrder())
                index++;

            // Insert it
            this.updateableComponents.insertAt(index, item);

            // Add handler (if none already exists)...
            item.add_updateOrderChanged(this._updateableUpdateOrderChangedDelegate);
        }
    }

    if (ajax.lang.implementsInterface(Object.getConstructorName(item), ajax.xna.framework.IDrawable.getFunctionName()))
    {
        item = ajax.xna.framework.IDrawable.cast(item);
        var index = this.drawableComponents.indexOf(item);
        if (index < 0)
        {           
            index = 0;
            while (index < this.drawableComponents.length && this.drawableComponents[index].get_drawOrder() >= item.get_drawOrder())
                index++;

            // insert it
            this.drawableComponents.insertAt(index, item);

            // add Handler
            item.add_drawOrderChanged(this._drawableDrawOrderChangedDelegate);
        }
    }
}


//-----------------------------------------------------------------------------
ajax.xna.framework.GameComponentCollection.prototype._updateableUpdateOrderChanged = function(e, r)
{
    e = ajax.events.EventArgs.cast(e);
    var item = ajax.xna.framework.IUpdateable.cast(e.sender);
    this.updateableComponents.remove(item);    
    this.add(item);
}
ajax.xna.framework.GameComponentCollection.prototype._updateableUpdateOrderChangedDelegate = null;
//-----------------------------------------------------------------------------
ajax.xna.framework.GameComponentCollection.prototype._drawableDrawOrderChanged = function(e, r)
{
    e = ajax.events.EventArgs.cast(e);
    var item = ajax.xna.framework.IDrawable.cast(e.sender);
    this.drawableComponents.remove(item);
    this.add(item);
}
ajax.xna.framework.GameComponentCollection.prototype._drawableDrawOrderChangedDelegate = null;

//-----------------------------------------------------------------------------
ajax.xna.framework.GameComponentCollection.prototype._onComponentRemoved = function(item)
{
    // Remove handlers and from internal lists.
    if (ajax.lang.implementsInterface(Object.getConstructorName(item), ajax.xna.framework.IUpdateable.getFunctionName()))
    {
        item = ajax.xna.framework.IUpdateable.cast(item);
        item.remove_updateOrderChanged(this._updateableUpdateOrderChangedDelegate);
        this.updateableComponents.remove(item);
    }
    if (ajax.lang.implementsInterface(Object.getConstructorName(item), ajax.xna.framework.IDrawable.getFunctionName()))
    {
        item = ajax.xna.framework.IDrawable.cast(item);
        item.remove_drawOrderChanged(this._drawableDrawOrderChangedDelegate);
        this.drawableComponents.remove(item);
    }
}


// Overrides
//-----------------------------------------------------------------------------
ajax.xna.framework.GameComponentCollection.prototype.add = function(item)
{///<param name="item" type="ajax.xna.framework.IGameComponent">The IGameComponent Item to add</param>         
    ajax.xna.framework.GameComponentCollection.superClass.add.apply(this, arguments);
    this._onComponentAdded(item); 
}
//-----------------------------------------------------------------------------
ajax.xna.framework.GameComponentCollection.prototype.addAt = function(index, item)
{///<param name="index" type="int" integer="true">The index position to add at.</param>
 ///<param name="item" type="ajax.xna.framework.IGameComponent">The item to add.</param>
    ajax.xna.framework.GameComponentCollection.superClass.addAt.apply(this, arguments);    
    this._onComponentAdded(item);
}
//-----------------------------------------------------------------------------
ajax.xna.framework.GameComponentCollection.prototype.insert = ajax.xna.framework.GameComponentCollection.prototype.addAt;
//-----------------------------------------------------------------------------
ajax.xna.framework.GameComponentCollection.prototype.remove = function(item)
{///<param name="item" type="ajax.xna.framework.IGameComponent">The Item to remove</param>
    ajax.xna.framework.GameComponentCollection.superClass.remove.apply(this, arguments);    
    this._onComponentRemoved(item);
}

//-----------------------------------------------------------------------------
ajax.xna.framework.GameComponentCollection.prototype.removeAt = function(index)
{///<param name="index" type="int" integer="true">The index of the Item to remove</param>   
    var item = this[index]; 
    ajax.xna.framework.GameComponentCollection.superClass.removeAt.apply(this, arguments);    
    this._onComponentRemoved(item);
}

// Statics
//-----------------------------------------------------------------------------
ajax.xna.framework.GameComponentCollection.cast = function(obj)
{///<returns type="ajax.xna.framework.GameComponentCollection"/>
    return obj;
}